Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic

Namespace KADGen.Utility

   ''' <summary>
   ''' This partial class contains methods ready for the new system
   ''' </summary>
   ''' <remarks></remarks>
   Public Class PluralSystem
      Public Structure PluralDef
         Public Sub New( _
               ByVal singular As String, _
               ByVal plural As String, _
               ByVal wholeWord As Boolean, _
               ByVal preferred As Boolean)
            Me.Singular = singular
            Me.Plural = plural
            Me.WholeWord = wholeWord
            Me.Preferred = preferred
         End Sub
         Public ReadOnly Singular As String
         Public ReadOnly Plural As String
         Public ReadOnly WholeWord As Boolean
         Public ReadOnly Preferred As Boolean
      End Structure

      Private Const pluralDefFileName As String = "PluralDefinitions.xml"

      Shared mBasePlural As List(Of PluralDef)
      Shared mOrganizationPlural As List(Of PluralDef)
      Shared mProjectPlural As List(Of PluralDef)

      Public Shared Function GetPluralFromLookup( _
               ByVal singular As String, _
               ByVal basePath As String) _
               As String
         If String.IsNullOrEmpty(singular) Then
            Return singular
         End If
         Dim ret As String
         OpenFilesIfNeeded(basePath)
         ret = PluralFromSingular(singular, mProjectPlural)
         If ret Is Nothing Then
            ret = PluralFromSingular(singular, mOrganizationPlural)
         End If
         If ret Is Nothing Then
            ret = PluralFromSingular(singular, mBasePlural)
         End If
         Return ret
      End Function

      Public Shared Function GetSingularFromLookup( _
                ByVal plural As String, _
                ByVal basePath As String) _
                As String
         If String.IsNullOrEmpty(plural) Then
            Return plural
         End If
         Dim ret As String
         OpenFilesIfNeeded(basePath)
         ret = SingularFromPlural(plural, mProjectPlural)
         If ret Is Nothing Then
            ret = SingularFromPlural(plural, mOrganizationPlural)
         End If
         If ret Is Nothing Then
            ret = SingularFromPlural(plural, mBasePlural)
         End If
         Return ret
      End Function

      Private Shared Sub OpenFilesIfNeeded(ByVal basePath As String)
         If mBasePlural Is Nothing Then
            OpenBasePluralSearch()
         End If
         If mOrganizationPlural Is Nothing Then
            OpenOrganizationPluralSearch()
         End If
         If mProjectPlural Is Nothing Then
            OpenProjectPluralSearch(basePath)
         End If
      End Sub

      Private Shared Sub OpenBasePluralSearch()
         If mBasePlural Is Nothing Then
            mBasePlural = New List(Of PluralDef)
            Dim assembly As Reflection.Assembly = GetType(PluralSystem).Assembly
            Dim resNames As String() = assembly.GetManifestResourceNames()
            Dim stream As IO.Stream = Nothing
            Try
               stream = assembly.GetManifestResourceStream(pluralDefFileName)
               mBasePlural = New List(Of PluralDef)
               If stream Is Nothing Then
                  Throw New System.Exception("The embedded resource for plural conversions is missing")
               End If
               Dim reader As Xml.XmlReader = Xml.XmlReader.Create(stream)
               LoadFromReader(reader, mBasePlural)
            Finally
               If stream IsNot Nothing Then
                  stream.Close()
               End If
            End Try
         End If
      End Sub

      Private Shared Sub OpenOrganizationPluralSearch()
         If mOrganizationPlural Is Nothing Then
            Dim path As String = My.Computer.FileSystem.SpecialDirectories.CurrentUserApplicationData
            Dim fileName As String = IO.Path.Combine(path, pluralDefFileName)
            mOrganizationPlural = New List(Of PluralDef)
            LoadFromFile(fileName, mOrganizationPlural)
         End If
      End Sub

      Private Shared Sub OpenProjectPluralSearch(ByVal basePath As String)
         If mProjectPlural Is Nothing Then
            Dim fileName As String = IO.Path.Combine(basePath, pluralDefFileName)
            mProjectPlural = New List(Of PluralDef)
            LoadFromFile(fileName, mProjectPlural)
         End If
      End Sub

      Private Shared Sub LoadFromFile(ByVal fileName As String, ByVal loadInto As List(Of PluralDef))
         If (IO.File.Exists(fileName)) Then
            Dim reader As Xml.XmlReader = Nothing
            Try
               reader = Xml.XmlReader.Create(fileName)
               LoadFromReader(reader, loadInto)
            Finally
               If reader IsNot Nothing Then
                  reader.Close()
               End If
            End Try
         End If
      End Sub

      Private Shared Sub LoadFromReader(ByVal reader As Xml.XmlReader, ByVal loadInto As List(Of PluralDef))
         While reader.Read
            If reader.LocalName = "PluralDef" Then
               Dim plural As String = reader.GetAttribute("Plural")
               Dim singular As String = reader.GetAttribute("Singular")
               Dim wholeWordString As String = reader.GetAttribute("WholeWord")
               Dim wholeWord As Boolean = False
               If Not String.IsNullOrEmpty(wholeWordString) AndAlso wholeWordString.ToLower = "true" Then
                  wholeWord = True
               End If
               Dim preferredString As String = reader.GetAttribute("Preferred")
               Dim preferred As Boolean = False
               If Not String.IsNullOrEmpty(preferredString) AndAlso preferredString.ToLower = "true" Then
                  preferred = True
               End If
               loadInto.Add(New PluralDef(singular, plural, wholeWord, preferred))
            End If
         End While
      End Sub

      Private Shared Function PluralFromSingular( _
               ByVal singular As String, _
               ByVal list As List(Of PluralDef)) _
               As String
         Dim ret As String = Nothing
         For Each def As PluralDef In list
            If singular.ToLower().EndsWith(def.Singular.ToLower()) Then
               ret = singular.Substring(0, singular.Length - def.Singular.Length) + def.Plural
               Exit For
            End If
         Next
         Return ret
      End Function

      Private Shared Function SingularFromPlural( _
            ByVal plural As String, _
            ByVal list As List(Of PluralDef)) _
            As String
         Dim ret As String = Nothing
         For Each def As PluralDef In list
            If plural.ToLower().EndsWith(def.Plural.ToLower()) Then
               ret = plural.Substring(0, plural.Length - def.Plural.Length) + def.Singular
               Exit For
            End If
         Next
         Return ret
      End Function



   End Class
End Namespace